---
--GamersArmy.net Main Server code.
--TTT GA mod
---

function AddDir(dir)
    print(dir)
	dir = tostring(dir)
    for k,v in pairs(file.Find(dir.."/*","GAME")) do
	    print(dir.."/"..v)
        resource.AddFile(dir.."/"..v,"GAME")
    end
end

AddCSLuaFile("CL_GAHud.lua")
AddCSLuaFile("cl_gainit.lua")
AddCSLuaFile("ga_shared.lua")
AddCSLuaFile("sh_utime.lua")
include("sh_utime.lua")
include("sv_utime.lua")

--billy files
resource.AddFile("models/player/billymays.mdl")
AddDir("materials/models/player/Billy")
AddDir("materials/models/BILLYMAYS")
--steve files
resource.AddFile("models/player/blockdude.mdl")
resource.AddFile("materials/models/player/blockdude/blockdude.vtf")
resource.AddFile("materials/models/player/blockdude/blockdude.vmt")
--quinn files
resource.AddFile("models/player/slow/arkham_asylum/harley_quinn/gmod_reskin.mdl")
resource.AddFile("models/cs_fix_f.mdl")
AddDir("materials/models/player/slow/arkham_asylum/harley_quinn/D00msdayDevice")
AddDir("materials/models/player/slow/arkham_asylum/harley_quinn/gmod")
--add dipsy
resource.AddFile("models/player/justpeople/dipsy_hl2mp_player.mdl")
AddDir("materials/models/player/dipsy_hl2mp")
--smith
resource.AddFile("models/characters/smith.mdl")
AddDir("materials/models/characters/smith")
--pyhead
AddDir("materials/models/characters/ph")
resource.AddFile("models/characters/pyramid_head.mdl")
--deadpool
AddDir("materials/models/apocmodels/deadpool/deadpool")
resource.AddFile("materials/models/apocmodels/deadpool/exponent.vtf")
resource.AddFile("models/apocmodels/deadpool/dyadyapoolya36.mdl")
resource.AddFile("models/weapons/c_arms_deadpool.mdl")
--lich king
AddDir("materials/models/maxxy/lich_king_enhanced")
resource.AddFile("models/player/lich_king_wow_maskless.mdl")
--Jack File
AddDir("materials/models/vinrax/jack_skellington")
resource.AddFile("models/vinrax/player/jack_player.mdl")
resource.AddFile("models/vinrax/weapons/c_arms_jack.mdl")

include("ga_shared.lua")
timercheck = 0
--set colors
greencolor = Color( 25, 200, 25 )
whitecolor = Color( 255, 255, 255 )
redcolor = Color( 255, 25, 25 )


resource.AddFile("models/ledmau5/ledmau5.mdl")
AddDir("materials/models/ledmau5")
AddDir("sound/mau5")
function deadmau( ply )
local offset = Vector(10,10,10)
local vec = ply:GetEyeTrace().HitPos + offset
print(vec)
if (not IsValid(ply)) or ply:IsAdmin() or ply:IsSuperAdmin() or cvars.Bool("sv_cheats", 0) then	
mau=ents.Create("prop_physics")
mau:SetModel("models/ledmau5/ledmau5.mdl")
mau:SetPos(vec)
mau:Activate()
mau:Spawn()
local maup = mau:GetPhysicsObject()
maup:SetMass( 10 )
end
end
function Ga_Initialize()
	tables_exist()
	print("GA Init")
end
--Init things
function tables_exist()
	if (sql.TableExists("ga_player_info") && sql.TableExists("ga_player_points")) then
		print("Both tables already exist !")
	else
		if (!sql.TableExists("ga_player_info")) then
			query = "CREATE TABLE ga_player_info ( unique_id varchar(255), money int )"
			result = sql.Query(query)
			if (sql.TableExists("ga_player_info")) then
				print("Succes ! table 1 created \n")
			else
				print("Somthing went wrong with the ga_player_info query ! \n")
				print( sql.LastError( result ) .. "\n" )
			end	
		end
		if (!sql.TableExists("ga_player_points")) then
			query = "CREATE TABLE ga_player_points ( unique_id varchar(255), speech int, fish int, farm int )"
			result = sql.Query(query)
			if (sql.TableExists("ga_player_points")) then
				print("Succes ! table 2 created \n")
			else
				print("Somthing went wrong with the ga_player_points query ! \n")
				print( sql.LastError( result ) .. "\n" )
			end	
		end
	end
 
end
--Lets check if the DB is made (if server is ever changed or if i add more tables)
function PlayerInitialSpawn( ply )  
	timer.Create("Steam_id_delay", 10, 1, function()
		SteamID = ply:SteamID()
		ply:SetNWString("SteamID", SteamID)
		timer.Create("SaveStat", 10, 0, function() saveStat( ply ) end)
		player_exists( ply ) 
	end)
 
 end
--set up save timers and get steamid networked
function PlayerSpawnChk( ply )
    if timercheck == 0 then
        PlayerInitialSpawn( ply )
    end
end
--this was a little recheck when i was having issues with data loading 
function ReSyncMoney( ply )
        SteamID = ply:SteamID()
		ply:SetNWString("SteamID", SteamID)
        player_exists( ply )
end
--Resync some data
function player_exists ( ply )
	steamID = ply:GetNWString("SteamID")
	result = sql.Query("SELECT unique_id, money FROM ga_player_info WHERE unique_id = '"..steamID.."'")
	timercheck = 1
	if (result) then
			sql_value_stats( ply ) // We will call this to retrieve the stats
			sql_value_skills( ply ) // We will call this to retrieve the skills
	else
		new_player( steamID, ply ) // Create a new player :D
	end
end
--Lets see if this player is in the db and then run the right functions.
function new_player( SteamID, ply )      
        plyname = ply:GetName()
        --PrintMessage( HUD_PRINTTALK, "Welcome ".. plyname .." to the server! This is there first time seen here!" )
	    ULib.tsayColor( nil, false, redcolor, ply:Nick(), whitecolor, " has joined the server for the first time! Welcome them!" )
		steamID = SteamID
		sql.Query( "INSERT INTO ga_player_info (`unique_id`, `money`)VALUES ('"..steamID.."', '100')" )
		result = sql.Query( "SELECT unique_id, money FROM ga_player_info WHERE unique_id = '"..steamID.."'" )
		if (result) then
 
			sql.Query( "INSERT INTO ga_player_points (`unique_id`, `speech`, `fish`, `farm`)VALUES ('"..steamID.."', '1', '1', '1')" )
			result = sql.Query( "SELECT unique_id, speech, fish, farm FROM ga_player_points WHERE unique_id = '"..steamID.."'" )
			if (result) then
				Msg("Player account created !\n")
				sql_value_stats( ply )
				sql_value_skills( ply )
			else
				Msg("Something went wrong with creating a players skills !\n")
			end
 
		else
			Msg("Something went wrong with creating a players info !\n")
		end
end
--Add new player data
function sql_value_stats ( ply )
	unique_id = sql.QueryValue("SELECT unique_id FROM ga_player_info WHERE unique_id = '"..steamID.."'")
	money = sql.QueryValue("SELECT money FROM ga_player_info WHERE unique_id = '"..steamID.."'")
	ply:SetNWString("unique_id", unique_id)
	ply:SetNWInt("money", money)
end
--Get player data (money)

function sql_value_skills ( ply )
    steamID = ply:GetNWString("SteamID")
	unique_id = sql.QueryValue("SELECT unique_id FROM ga_player_points WHERE unique_id = '"..steamID.."'")
    gAModel = sql.QueryValue("SELECT speech FROM ga_player_points WHERE unique_id = '"..steamID.."'")
	gATime = sql.QueryValue("SELECT fish FROM ga_player_points WHERE unique_id = '"..steamID.."'")
	gATime = tonumber(gATime)
	gAModel = tonumber(gAModel)
	if gAModel == 0 then
	gAModel = 1
	end
	--Why is a number not a int if its stored in sql as a int but comes back as a var that is still a number? what? 
	--It took me 2 hours to find this simple fix...
	farm = sql.QueryValue("SELECT farm FROM ga_player_points WHERE unique_id = '"..steamID.."'")
	ply:SetNWString("unique_id", unique_id)	
	--print(gAmodel)
	ply:SetNWInt("model", gAModel)
	--ply:SetNWInt("timeint", gATime)
	ply:SetNWInt("farm", farm)
	--ULib.tsayColor( nil, false, redcolor, ply:Nick(), whitecolor, " has joined the server! They have been playing here for: "..gATime.." minutes")
	end	
function gaDissconnect (ply)
saveStat(ply)
end
--lets save on disconnect.
function gaRoundStart ( )
timer.Create("Modelcheck", 1, 1, gaModelCheck)
end
--Just some stuff to call on the start of a round
function gaModelCheck()
print("modelthing")
 local allplayers = player.GetAll( )
   for k,v in pairs ( allplayers ) do         
        local gAModel = v:GetNWInt("model")
		local nn = tonumber(gAModel)
		print(nn)
		if nn ~= 1 then
        if gamod[gAModel] then
		    --print("set model thing")
			--print(gamod[gAModel])
	        v:SetModel(gamod[gAModel])
    	end
		else
		print("na bro you set to none")
		end
	end
end
--If they own a model then lets set the model.
function addMoney (ply,command,add)
    local greencolor = Color( 25, 200, 25 )
    local whitecolor = Color( 255, 255, 255 )
    local redcolor = Color( 255, 25, 25 )
 
	local add = string.Explode(" ", add)
    add = add[1]
    money = ply:GetNWInt("money")
	--print("money "..money)
	unique_id = ply:GetNWString ("SteamID")
	--print("add"..command)
    money = money + add
	ply:SetNWInt("money", money)
	saveStat(ply)
    ULib.tsayColor( nil, false, redcolor, ply:Nick(), whitecolor, " Now has $".. money )
	--print("money added, new total: $"..money)	
end
--Give the player some money!
function addMoneyquite (ply,add)
	money = ply:GetNWInt("money")
	print("money quite "..money)
	unique_id = ply:GetNWString ("SteamID")
	print("add quite "..add)
    money = money + add
	ply:SetNWInt("money", money)
   -- ULib.tsayColor( nil, false, redcolor, ply:Nick(), whitecolor, " Now has $".. money )
	--print("money added, new total: $"..money)	
end
--Add money without a reply
function MoneyChat (ply, text) 
    local txt = string.Explode(" ", text)
    if (txt[1] == "!add") then
	    if (not IsValid(ply)) or ply:IsAdmin() or ply:IsSuperAdmin() or cvars.Bool("sv_cheats", 0) then		
	        --print("Well we got here")
	        local uf = ULib.getUser(txt[2])
		    if ((uf != false)&&(uf != nil)&&(txt[3])) then
		        --local uf = uf:UniqueID()
		       -- print("wtf its working")
		        addMoney(uf,add,txt[3])
		    else
		        ULib.tsayError( target_plys, "Some kinda error with your command!?", true )
		    end
	    else
		     ULib.tsayError( target_plys, "You must be a GMod Admin or SuperAdmin on the server to use this command", true )
	    end
	elseif (txt[1] == "!toptime") then
	topTime()
	elseif (txt[1] == "!topmoney") then
	topMoney()
	elseif (txt[1] == "!models") then
	ULib.tsayError( ply, "list of models:", true )
	for i = 1, #gamodnamelocal do
    ULib.tsayError( ply, gamodnamelocal[i], true )
    end	
    elseif (txt[1] == "!model") then
	    if not txt[2] then
		gAmodel = ply:GetNWInt("model")
		--print("the model is")
		--print(gAmodel)
		if gamodnamelocal[gAmodel] then
		gAmodel = gamodnamelocal[gAmodel] 
		else
		gAmodel = "none"
		end
		ply:PrintMessage( HUD_PRINTTALK, "Your model is set to: "..gAmodel )
		--ULib.tsayError( target_plys, "Your model is set to: "..gAmodel, true )
		else
	    if (not IsValid(ply)) or ply:IsAdmin() or ply:IsSuperAdmin() or cvars.Bool("sv_cheats", 0) then
	        local uf = ULib.getUser(txt[2])
		    if ((uf != false)&&(uf != nil)&&(txt[3])) then
		        if (gamodnamechat[txt[3]] and not txt[3] == "none" ) then
				    uf:SetNWInt("model", gamodnamechat[txt[3]])
					uf:SetModel(gamod[gamodnamechat[txt[3]]])
					target_plys:PrintMessage( HUD_PRINTTALK, "model updated!" )
					uf:PrintMessage( HUD_PRINTTALK, "Your model has been updated!" )
					saveStat(uf)
				elseif (txt[3] == "none") then
				    uf:SetNWInt("model", 1)
				   	target_plys:PrintMessage( HUD_PRINTTALK, "model updated!" )
					uf:PrintMessage( HUD_PRINTTALK, "Your model has been updated!" )
					saveStat(uf)
				else
				    ply:PrintMessage( HUD_PRINTTALK, "Not a valid model!" )
				    --ULib.tsayError( target_plys, "Not a valid model!", true )
				end
		    else
			    ply:PrintMessage( HUD_PRINTTALK, "Some kinda error with your command!?" )
		       --ULib.tsayError( target_plys, "Some kinda error with your command!?", true )
		    end
	    else
		     ULib.tsayError( target_plys, "You must be a GMod Admin or SuperAdmin on the server to use this command", true )
	    end
		end
	end
	--print("lul")
end
--add some chat commands (started out as just money commands it now runs all the GA commands ha)
function saveStat ( ply )
	money = ply:GetNWInt("money")
	unique_id = ply:GetNWString ("SteamID")
	gAmodel = ply:GetNWInt("model")
	fish = 1
	farm = 1
	local result = sql.Query("UPDATE ga_player_info SET money = "..money.." WHERE unique_id = '"..unique_id.."'")
	local result = sql.Query("UPDATE ga_player_points SET speech = "..gAmodel.." WHERE unique_id = '"..unique_id.."'")

end
--Main save (called by timer)
 function saveStat2 ( ply , var, mon )
	money = ply:GetNWInt("money")
	print("money"..money)
	if mon[1] then
	print("var"..mon[1])
	money = string.Explode(".", mon[1])
	money = money[1]
	--money = string.Left(mon[1], 3)
	end
	ply:SetNWInt("money", money)
	unique_id = ply:GetNWString ("SteamID")
	sql.Query("UPDATE ga_player_info SET money = "..money.." WHERE unique_id = '"..unique_id.."'")
	print("Stats updated! Saved $"..money) // Added a nice little message
	ReSyncMoney(ply)
end
--Other way to save (more checking on money called by money) 
 function ShowGaMu( ply )
	ply:ConCommand( "GaMenu" )
end
--This can most likely be removed.... We did not need a function for this (aka why i sould not drink and code)
function DSwitchTest( ply )
            
			ply:SetRole(ROLE_DETECTIVE)
            ply:AddCredits(GetConVarNumber("ttt_credits_starting"))
            ply:Give("weapon_ttt_wtester")
			ply:ChatPrint("You have paid to be a detective this round.")
end
--server side of buying D round
function TSwitchTest( ply )          
			ply:SetRole(ROLE_TRAITOR)
            ply:AddCredits(GetConVarNumber("ttt_credits_starting"))
			ply:ChatPrint("You have paid to be a traitor this round.")
end
--server side of buying T round
local function EndCred(wintype)
   local allplayers = player.GetAll( )
   for k,v in pairs ( allplayers ) do 
       -- print("check")  		
        if wintype == WIN_INNOCENT then
		--   print("win inno")	
           		   
	         if v:IsPlayer() && (not v:GetTraitor()) then
			            if v:IsDetective() then
				            --add $20
				            addMoneyquite(v,20)
				            v:ChatPrint("You have earned $20 for winning the round as a Detective!")
                        elseif v:Alive() then
				          --add $10
				            addMoneyquite(v,10)
				            v:ChatPrint("You have earned $10 for winning the round and staying alive!")
				        else
				            addMoneyquite(v,2)
				            v:ChatPrint("You have earned $2 for winning the round you could of earned more if you stayed alive!")
                            --add $2			
				       end
					   --end is trat
			        end    
		end
        if wintype == WIN_TRAITOR then
		--print("win T")
		    if v:IsTerror() then
			    if v:Alive() then
				    addMoneyquite(v,25)
				    v:ChatPrint("You have earned $25 for winning the round and staying alive!")
				    --add 25
				else
				    addMoneyquite(v,10)
				    v:ChatPrint("You have earned $10 for winning the round you could of earned more if you stayed alive!")
				   --add $10
				end
			end
		end
        if wintype == WIN_TIMELIMIT then
		    v:ChatPrint("No winners? No pay!")
           --Give money to noone..
        end		
   end
  -- print("end check")
end
--lets give them some money for winning
hook.Add("TTTEndRound", "EndCred", EndCred)
function buymodel(ply,CN,arg)
    money = ply:GetNWInt("money")
    money = tonumber(money)
    id = tonumber(arg[1])
	if gamod[id] then
    cost = tonumber(gamodprice[id])
    if money > cost then
        --ULib.tsayError( ply, "buying model", true )
        if id > 1 then 		     
            spendMoney( ply, cost)
			ply:SetNWInt("model", id)
			ply:SetModel(gamod[id])
			ULib.tsay(_,ply:Nick().." has updated there model! It cost them $"..cost)
            ply:PrintMessage( HUD_PRINTTALK, "Your model has been updated!" )
            saveStat(ply)
        else 
            ply:SetNWInt("model", 1)
			ULib.tsay(_,ply:Nick().." has switch back to a stock model")
            ply:PrintMessage( HUD_PRINTTALK, "Your model has been removed!" )
            saveStat(ply)
        end
    else 
        ULib.tsayError( ply, "You don't have enough money!", true )
    end
	else
	--print("error")
	ULib.tsayError( ply, "You did something wrong... idiot", true )
	end
end
--Lets buy a model lul
function saveAll()
	local players = player.GetAll()
	for _, ply in ipairs( players ) do
		if ply and ply:IsConnected() then
			saveStat(ply)
		end
	end
end
function topTime()
local timesort = {}
local moneytime = {}
   local players = player.GetAll()
	for _, ply in ipairs( players ) do
	if ply and ply:IsConnected() then	   
		   local temptime = math.Round(ply:GetUTime() + CurTime() - ply:GetUTimeStart())
			timesort[temptime] = ply:Nick()
			moneytime[temptime] = ply:GetNWInt("money")
			end
	end
PrintTable(timesort)
	local timesorted = table.SortByKey(timesort, true)
	local ct = 1	
	PrintTable(timesorted)
	table.SortDesc(timesorted)
	print("--------------------------------")
	PrintTable(timesorted)
  for i, v in ipairs(timesorted) do
    if ct == 1 then
	print("Top player in server is: ".. v)
	ULib.tsayColor( nil, false, greencolor, "TIME", whitecolor, " Top player in server is: ".. timesort[v] .." They have been playing here for: ".. timeToStr(v) .." They have $".. moneytime[v] .." on them!")
	elseif ct > 1 and ct <= 5 then
	ULib.tsayColor( nil, false, greencolor, "TIME", whitecolor, " Number ".. ct .." is: ".. timesort[v] .." They have been here".. timeToStr(v) .."!")
	end 
	ct = ct+1
 end
end
function topMoney()
local moneysort = {}
local moneysort2 = {}
   local players = player.GetAll()
	for _, ply in ipairs( players ) do
	if ply and ply:IsConnected() then	   
		   local tempmoney = ply:GetNWInt("money")
			moneysort[tonumber(tempmoney)] = ply:Nick()
			end
	end
	PrintTable(moneysort)
	local moneysort2 = table.SortByKey(moneysort, true)
	local ct = 1	
	PrintTable(moneysort2)
	table.SortDesc(moneysort2)
	print("--------------------------------")
	PrintTable(moneysort2)
  for i, v in ipairs(moneysort2) do
    if ct == 1 then
	print("Top player in server is: ".. v)
	ULib.tsayColor( nil, false, greencolor, "MONEY", whitecolor, " Player with the most money in the server is: ".. moneysort[v] .." They have $".. v .."!!!")
	elseif ct > 1 and ct <= 5 then
	ULib.tsayColor( nil, false, greencolor, "MONEY", whitecolor, " Number ".. ct .." is: ".. moneysort[v] .." They have $".. v .."!!!")
	end 
	
	ct = ct+1
 end
 table.Empty(moneysort2)
 table.Empty(moneysort)
end
function timeToStr( time )
	local tmp = time
	local s = tmp % 60
	tmp = math.floor( tmp / 60 )
	local m = tmp % 60
	tmp = math.floor( tmp / 60 )
	local h = tmp % 24
	tmp = math.floor( tmp / 24 )
	local d = tmp % 7
	local w = math.floor( tmp / 7 )
    if w != 0 then
	return string.format( "%02iw %id %02ih %02im %02is", w, d, h, m, s )
	elseif d != 0 then
	return string.format( "%id %02ih %02im %02is", d, h, m, s )
	elseif h != 0 then
	return string.format( "%02ih %02im %02is", h, m, s )
	else
	return string.format( "%02im %02is", m, s )
	end
end
function sayuid(ply)
local uid = ply:UniqueID()
print("uid="..uid)
end

function buyweapon(ply,CN,arg)
if ply:Alive() and (not ply:IsSpec())  then
    money = ply:GetNWInt("money")
    money = tonumber(money)
    id = tonumber(arg[1])
	if weaps[id] then
	if 	ply:IsUserGroup("protected") or ply:IsUserGroup("admin")  or ply:IsUserGroup("superadmin") then
	cost = weaps[id].prices.dic
	ULib.tsay(ply,"You got this item at a discount!")
	else
	cost = weaps[id].prices.reg
	end
	cost = tonumber(cost)
	if money > cost then
	ply:Give(weaps[id].swep)
	spendMoney( ply, cost)
	saveStat(ply)
	else
	  ULib.tsayError( ply, "You don't have enough money!", true )
    end
    else
		ULib.tsayError("", "You did something wrong... idiot.. data- ID:"..id, true )
	end
	else
	ULib.tsayError( ply, "Why are you trying to buy a gun when you are dead?!", true )
	end
end
timer.Create( "gaSaveTimer", 67, 0, saveAll )
--ConCommands and hooks
concommand.Add("buyweapon", buyweapon)
concommand.Add("buymodel", buymodel)
concommand.Add("sayuid", sayuid)
concommand.Add("testb", sql_value_skills )
concommand.Add("savestat",saveStat2)
concommand.Add("resync",ReSyncMoney)
concommand.Add("deadmau",deadmau)
concommand.Add("ga1",DSwitchTest)
concommand.Add("ga2",TSwitchTest)
concommand.Add("BuyClass",gabuyclass)
hook.Add( "PlayerDisconnected", "gaDissconnect", gaDissconnect )
hook.Add("TTTPrepareRound", "GaRoundStart", gaRoundStart)
hook.Add("TTTBeginRound", "GaRoundStart2", gaRoundStart)
hook.Add("PlayerSpawn ", "GaRoundStart3", gaRoundStart)
hook.Add("PlayerSay", "MoneyChat", MoneyChat)
hook.Add("ShowSpare1", "GaMenu", ShowGaMu)
hook.Add("PlayerSpawn", "SpawnCheck", PlayerSpawnChk)
hook.Add( "PlayerInitialSpawn", "PlayerInitialSpawn", PlayerInitialSpawn )
hook.Add( "InitPostEntity", "gaInitialize", Ga_Initialize )
print("Loaded GA Main")